#include "fml_ota.h"
#include "cJSON.h"
#include "md_5.h"


OTA_INFO g_ota_info;
cJSON *g_ota_info_json = NULL;

int32_t fml_ota_init(void)
{
    cJSON *p_root = NULL;
    cJSON *p_item = NULL;
    uint8_t *str_buff = NULL;
    int32_t ret = 0;

    memset(&g_ota_info, 0, sizeof(g_ota_info));
    
    str_buff = (uint8_t *)malloc(FLASH_PAGE_SIZE);
    if (str_buff == NULL)
        return -1;
    
    hal_flash_read(str_buff, CONFIG_START_ADDR, FLASH_PAGE_SIZE);
    
    p_root = cJSON_Parse(str_buff);
    if (NULL == p_root)
    {
        printf("Parse OTA info obj failed\r\n");
        ret = -2;
        goto mem_free;
    }

    p_item = cJSON_GetObjectItem(p_root, "app_update_flag");
    if (NULL == p_item)
    {
        printf("Get app_update_flag item failed\r\n");
        ret = -3;
        goto mem_free;
    }
    else
    {
        g_ota_info.app_update_flag = p_item->valueint;
        printf("app_update_flag: %d\r\n", g_ota_info.app_update_flag);
    }
    
    p_item = cJSON_GetObjectItem(p_root, "app_version");
    if (NULL == p_item)
    {
        printf("Get app_version item failed\r\n");
        ret = -4;
        goto mem_free;
    }
    else
    {
        strcpy(g_ota_info.app_version, p_item->valuestring);
        printf("app_version:%s\r\n", g_ota_info.app_version);
    }
    
    p_item = cJSON_GetObjectItem(p_root, "app_md5");
    if (NULL == p_item)
    {
        printf("Get app_md5 item failed\r\n");
        ret = -5;
        goto mem_free;
    }
    else
    {
        strcpy(g_ota_info.app_md5, p_item->valuestring);
        printf("app_md5:%s\r\n", g_ota_info.app_md5);
    }

    p_item = cJSON_GetObjectItem(p_root, "json_data_md5");
    if (NULL == p_item)
    {
        printf("Get json_data_md5 item failed\r\n");
        ret = -6;
        goto mem_free;
    }
    else
    {
        strcpy(g_ota_info.json_data_md5, p_item->valuestring);
        printf("json_data_md5:%s\r\n", g_ota_info.json_data_md5);
    }

    g_ota_info_json = p_root;

mem_free:
    if (str_buff)
        free(str_buff);

    return ret;
}

int32_t fml_ota_flash_erase(uint32_t erase_addr, uint32_t size)
{
    return hal_flash_erase(erase_addr, size);
}

int32_t fml_ota_flash_read(uint8_t *p_data, uint32_t read_addr, uint32_t size)
{
    return hal_flash_read(p_data, read_addr, size);
}

int32_t fml_ota_flash_write(uint8_t *p_data, uint32_t write_addr, uint32_t size)
{
    return hal_flash_write(p_data, write_addr, size);
}

int32_t fml_ota_app_md5_calc(uint32_t addr, int32_t len, uint8_t *md5_out)
{
	MD5_CTX_T ctx;
	uint8_t i = 0;
	int32_t cur = 0, calc_len = 0;
	//uint8_t md5[32] = {0};
	uint8_t *p_calc = (uint8_t *)malloc(512);
    
	if (p_calc == NULL)
    {
        printf("malloc mem for md5 calc fail\r\n");
		return -1;
	}
    
	if (len <= 0)
    {
		printf("get a err len for data to check md5\r\n");
		return -1;
	}
    
	calc_len = len;
	md5_init(&ctx);
	while (true)
    {
		calc_len = len - cur;
		if (calc_len >= 512)
        {
			//GD_read_fast(p_calc, addr + cur, 512);
            fml_ota_flash_read(p_calc, addr + cur, 512);
			md5_update(&ctx, p_calc, 512);
		} 
		else
        {
			//GD_read_fast(p_calc, addr + cur, calc_len);
            fml_ota_flash_read(p_calc, addr + cur, calc_len);
			md5_update(&ctx, p_calc, calc_len);
			break;
		}
		memset(p_calc, 0, 512);
		cur += 512;
	}
    
	md5_final(&ctx, md5_out);
    
	//for (i = 0; i < 16; i++)
	//	sprintf((char *)md5_out + 2 * i, "%02x", md5[i]);

	free(p_calc);

	return 0;
}
